#ifndef __SERVER_HPP__
#define __SERVER_HPP__

#include <cstdint>

#include "error.hpp"
#include "log.hpp"
#include "socket.hpp"
#include "buffer.hpp"
#include "channel.hpp"
#include "poller.hpp"
#include "eventloop.hpp"
#include "connection.hpp"
#include "acceptor.hpp"
#include "loopthread.hpp"

#include <signal.h>

class NetWork
{
    static void handle_sigpipe(int signo)
    {
        DBG_LOG("recv SIGPIPE, done");
    }
public:
    NetWork()
    {
        DBG_LOG("SIGPIPE handle init");
        signal(SIGPIPE, handle_sigpipe);
    }
};
static NetWork nw;

class TcpServer
{
    using ConnectedCallback = std::function<void(const PtrConnection &)>;
    using MessageCallback = std::function<void(const PtrConnection &, Buffer *)>;
    using CloseCallback = std::function<void(const PtrConnection &)>;
    using EventCallback = std::function<void(const PtrConnection &)>;

public:
    TcpServer(uint16_t port) : _conn_id(0), _task_id(0), _port(port), _enable_inactive_release(false),
                               _acceptor(&_base_loop, _port), _loop_thread_pool(&_base_loop)
    {
        // 2. 设置新连接到来的回调函数
        _acceptor.SetAcceptCallback(std::bind(&TcpServer::NewConnection, this, std::placeholders::_1));
        // 3. 开始监听
        _acceptor.Listen();
    }
    /* 设置从属线程的最大数量 */
    void SetThreadCount(int count)
    {
        _loop_thread_pool.SetThreadCount(count);
    }
    /* 启动服务器 */
    void Start()
    {
        // 1. 创建线程池
        _loop_thread_pool.Create();
        
        // 4. 运行
        _base_loop.Start();
    }
    /* 设置回调函数 */
    void SetConnectedCallback(const ConnectedCallback &cb)
    {
        _connected_callback = cb;
    }
    void SetMessageCallback(const MessageCallback &cb)
    {
        _message_callback = cb;
    }
    void SetCloseCallback(const CloseCallback &cb)
    {
        _close_callback = cb;
    }
    void SetEventCallback(const EventCallback &cb)
    {
        _event_callback = cb;
    }
    /* 启动非活跃连接销毁功能 */
    void EnableInactiveRelease(int timeout)
    {
        // 1. 设置基准超时时间
        _timeout = timeout;
        // 2. 设置非活跃连接释放标志为启动状态
        _enable_inactive_release = true;
    }
    /* 执行指定定时任务 */
    void RunTimerTask(const Functor &task, int timeout)
    {
        _base_loop.RunInLoop(std::bind(&TcpServer::RunTimerTaskInLoop, this, task, timeout));
    }

private:
    /* 为新连接构建一个Connection对象，来对连接进行管理 */
    void NewConnection(int sockfd)
    {
        ++_conn_id;

        PtrConnection conn(new Connection(_loop_thread_pool.NextLoop(), _conn_id, sockfd));
        conn->SetCloseCallback(_close_callback);
        conn->SetConnectedCallback(_connected_callback);
        conn->SetMessageCallback(_message_callback);
        conn->SetEventCallback(_event_callback);
        conn->SetSvrCloseCallback(std::bind(&TcpServer::RemoveConnection, this, std::placeholders::_1));

        if(_enable_inactive_release)
            conn->EnableInactiveRelease(_timeout);// 启动非活跃连接超时销毁

        conn->Established();// 连接初始化

        _conns.insert(std::make_pair(_conn_id, conn));
    }
    void RemoveConnectionInLoop(const PtrConnection & conn)
    {
        uint64_t id = conn->Id();
        _conns.erase(id);
    }
    /* 关闭连接，移除Connection */
    void RemoveConnection(const PtrConnection & conn)
    {
        _base_loop.RunInLoop(std::bind(&TcpServer::RemoveConnectionInLoop, this, conn));
    }
    /* 在对应线程中执行定时任务 */
    void RunTimerTaskInLoop(const Functor &task, int timeout)
    {
        ++_task_id;
        _base_loop.TimerAdd(_task_id, timeout, task);
    }

private:
    uint64_t _conn_id;                                  // 连接id，自增长
    uint64_t _task_id;                                  // 任务id
    uint16_t _port;                                     // 监听的端口
    EventLoop _base_loop;                               // 主线程对应的EventLoop对象，负责对监听连接的事件管理
    Acceptor _acceptor;                                 // 对监听套接字的管理的对象
    std::unordered_map<uint64_t, PtrConnection> _conns; // 保存管理所有连接的shared_ptr对象
    LoopThreadPool _loop_thread_pool;                   // 从属EventLoop线程池

    int _timeout;                  // 非活跃连接的标准认定时间——多长时间没有通信就是非活跃连接
    bool _enable_inactive_release; // 是否启动非活跃连接销毁的标志

    ConnectedCallback _connected_callback; // 连接建立的回调函数
    MessageCallback _message_callback;     // 数据到来的回调函数
    CloseCallback _close_callback;         // 连接关闭的回调函数
    EventCallback _event_callback;         // 任意事件产生的回调函数
};

#endif